package org.nacos.provider.service.impl;

import java.util.*;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.nacos.provider.converter.ProductCovertBasic;
import org.nacos.provider.dataobject.ProductDO;
import org.nacos.provider.entity.*;
import org.nacos.provider.mapper.ProductMapper;
import org.nacos.provider.service.IAccountService;
import org.nacos.provider.service.ProductService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;


@Service
@Slf4j
public class ProductServiceImpl implements ProductService {

	@Resource
    private IAccountService accountService;
	
	@Resource
    private ProductMapper productMapper;
	
	private static final Logger logger = LoggerFactory.getLogger(ProductServiceImpl.class);
	
	@Override
	public Map<String, Object> queryProductInfo(Integer productId) {
		Map<String,Object> paramMap = new HashMap<>();
		paramMap.put("user_id", 2);
		accountService.removeByMap(paramMap);
		HashMap<String, Object> map = new HashMap<>(16);
		map.put("product_id", productId);
		return map;
	}

	/**
	 * 条件构造器的几种创建方法:
	 * 一、QueryWrapper<>
	 *  - QueryWrapper<ProductDO> wrapper = new QueryWrapper<>();
	 * 二、LambdaQueryWrapper<>
	 *  - LambdaQueryWrapper<ProductDO> lambda2 = new LambdaQueryWrapper<>();
	 *  - LambdaQueryWrapper<ProductDO> lambda = new QueryWrapper<ProductDO>().lambda();
	 *  - LambdaQueryWrapper<ProductDO> lambda3 = Wrappers.<ProductDO>lambdaQuery();
	 *  - LambdaQueryWrapper<ProductDO> lambda4 = Wrappers.lambdaQuery(ProductDO.class);
	 * 三、LambdaQueryChainWrapper<>
	 *  - new LambdaQueryChainWrapper<ProductDO>(productMapper).list();
	 *
	 *  分页插件
	 *  1. 在 MybatisPlusInterceptor 配置加入分页插件拦截器  PaginationInnerInterceptor
	 *  2. 分页参数 Page<T> 使用，默认会先执行 COUNT 查询获取总数，再执行分页 SQL
	 *  - 性能调优：可通过 page.setSearchCount(false) 关闭自动计算总数以提升性能
	 */

	@Override
	public List<ProductDO> queryProduct(Integer productId) {
		QueryWrapper<ProductDO> wrapper = new QueryWrapper<>();
		wrapper.eq("id", productId);
		// 引入 lambda，避免我们在代码中写类似的于 id 的硬编码
		// wrapper.lambda().eq(ProductDO::getId, id);
		List<ProductDO> prods = productMapper.selectList(wrapper);
		prods.forEach(System.out::println);
		
        LambdaQueryWrapper<ProductDO> lambda = Wrappers.lambdaQuery();
        lambda.eq(ProductDO::getId, productId);
        prods = productMapper.selectList(lambda);
        prods.forEach(System.out::println);
        
        prods = new LambdaQueryChainWrapper<>(productMapper)
        	.eq(ProductDO::getId, productId).list();
        prods.forEach(System.out::println);
		return prods;
	}

	@Override
	public PageBaseDTO<ProductDO> queryProductPage(Integer pageNo, Integer pageSize) {
		Page<ProductDO> page = new Page<>(pageNo, pageSize);
		String prodName = "分页查询";
		// 使用 Mapper 自定义分页查询
		QueryWrapper<ProductDO> wrapper = new QueryWrapper<>();
		wrapper.like("prod_name", prodName);
		Page<ProductDO> result = productMapper.selectPage(page, wrapper);
		PageBaseDTO<ProductDO> warpperBuild = PageBaseDTO.build(result.getRecords(), result.getTotal());
		logger.info("wrapper page:" + warpperBuild);
		// 使用自定义 SQL 分页查询
		Page<ProductDO> res = productMapper.selectInfoPage(page, prodName);
		PageBaseDTO<ProductDO> sqlBuild = PageBaseDTO.build(res.getRecords(), res.getTotal());
		logger.info("sql page:" + sqlBuild);
		return sqlBuild;
	}

	@Override
	public String productConvert() {
		ProductDO productDO = ProductDO.builder()
                .id(2)
                .prodName("键盘")
                .prodCount(1)
                .desc("2024-04-28 00:00:00")
                .build();

        // 使用 mapstruct
        ProductDTO1 productDTO1 = ProductCovertBasic.INSTANCE.toConvertVO1(productDO);
        logger.info("mapstruct productDO -> productDTO1:" + productDTO1);
		logger.info("mapstruct ignore id productDO -> productDTO1:" + ProductCovertBasic.INSTANCE.toIgnoreIdConvertVO1(productDO));
		logger.info("mapstruct ignore all productDO -> productDTO1:" + ProductCovertBasic.INSTANCE.toIgnoreAllConvertVO1(productDO));
        logger.info("mapstruct productDTO1 -> productDO:" + ProductCovertBasic.INSTANCE.fromConvertEntity1(productDTO1));
        logger.info("mapstruct productDO -> productDTO2:" + ProductCovertBasic.INSTANCE.toConvertVO2(productDO));
       
        // 使用 BeanUtils
        ProductDTO2 productDTO2 = new ProductDTO2();
        BeanUtils.copyProperties(productDO, productDTO2);
        logger.info("BeanUtils productDO -> productDTO2:" + productDTO2);
        
        // 类型变化，使用 mapstruct
        ProductDTO3 productDTO3 = ProductCovertBasic.INSTANCE.toConvertVO3(productDO);
        logger.info("mapstruct productDO -> productDTO3:" + productDTO3);
        logger.info("mapstruct productDTO3 -> productDO:" + ProductCovertBasic.INSTANCE.fromConvertEntity3(productDTO3));
        
		return "success";
	}

	@Override
	public String productValid(ProductDTO4 productDTO4) {
		// 获得验证器
		Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
		// 执行验证
		Set<ConstraintViolation<ProductDTO4>> validators = validator.validate(productDTO4, ProductDTO4.Update.class);
		for (ConstraintViolation<ProductDTO4> constraintViolation : validators) {
			log.info("代码校验 " + constraintViolation.getMessage());
		}
		return "success";
	}

}
